package com.magnate.software.thrift.service.proxy;

import org.apache.thrift.TException;
import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.protocol.TProtocolFactory;
import org.apache.thrift.transport.TIOStreamTransport;
import org.apache.thrift.transport.TTransport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Constructor;

public class ThriftServletProxy extends HttpServlet {

    /**
     *
     */
    private static final long serialVersionUID = -7715940578986995450L;

    private Logger logger = LoggerFactory.getLogger(ThriftServletProxy.class);

    private final TProcessor processor;

    private final TProtocolFactory inProtocolFactory;

    private final TProtocolFactory outProtocolFactory;


    @SuppressWarnings({"rawtypes", "unchecked"})
    public ThriftServletProxy(String serviceInterface, String serviceIFace,
                              Object serviceImplObject) throws Exception {
        super();

        // 当前接口
        //Service = Class.forName(serviceInterface);

        Class Processor = Class.forName(serviceInterface + "$Processor");
        Class iFace = Class.forName(StringUtils.hasText(serviceIFace) ?
                serviceIFace : serviceInterface + "$Iface");
        Constructor con = Processor.getConstructor(iFace);
        TProcessor processor = (TProcessor) con.newInstance(serviceImplObject);

        this.processor = processor;
        this.inProtocolFactory = new TCompactProtocol.Factory();
        this.outProtocolFactory = new TCompactProtocol.Factory();

    }

    public ThriftServletProxy(String serviceInterface, Object serviceImplObject)
            throws Exception {
        this(serviceInterface, null, serviceImplObject);

    }

    /**
     * @see HttpServlet#HttpServlet()
     */
    public ThriftServletProxy(TProcessor processor,
                              TProtocolFactory inProtocolFactory,
                              TProtocolFactory outProtocolFactory) {
        super();
        this.processor = processor;
        this.inProtocolFactory = inProtocolFactory;
        this.outProtocolFactory = outProtocolFactory;
    }

    /**
     * @see HttpServlet#HttpServlet()
     */
    public ThriftServletProxy(TProcessor processor,
                              TProtocolFactory protocolFactory) {
        this(processor, protocolFactory, protocolFactory);
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
     * response)
     */
    @SuppressWarnings("rawtypes")
    @Override
    protected void doPost(HttpServletRequest request,
                          HttpServletResponse response) throws ServletException, IOException {

        TTransport inTransport = null;
        TTransport outTransport = null;

        //String tmpname = Service.getName();

        try {
            response.setContentType("application/x-thrift");

            /**
             Enumeration e =request.getHeaderNames();
             while(e.hasMoreElements()){
             String name = (String)e.nextElement();
             logger.info("******header: " + name + "->" + request.getHeader(name));
             }
             */

            InputStream in = request.getInputStream();
            OutputStream out = response.getOutputStream();

            TTransport transport = new TIOStreamTransport(in, out);
            inTransport = transport;
            outTransport = transport;

            TProtocol inProtocol = inProtocolFactory.getProtocol(inTransport);
            TProtocol outProtocol = outProtocolFactory
                    .getProtocol(outTransport);

            processor.process(inProtocol, outProtocol);

            //LoggerUtility.returnInvoke();

            out.flush();
        } catch (TException te) {
            throw new ServletException(te);
        }
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
     * response)
     */
    protected void doGet(HttpServletRequest request,
                         HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}
